﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace Tzync
{
   public class Sync
    {
        private List<Difference> differences;
        private List<TreeNode> arrNodes;
        private Stack<Difference> folderStack;
        private SystemType systemName;
        private String storeFilesDir, rootAddress;
        bool secondTime;

        // Constructor called for first time and second syncing
        public Sync(List<TreeNode> arrNodes,bool sT,SystemType st)
        {
            this.arrNodes = arrNodes;
            secondTime = sT;
            systemName = st;

            storeFilesDir = Directory.GetCurrentDirectory();
            storeFilesDir = Path.Combine(storeFilesDir, @"Tzync\Files");
            //Creating the directory
            Directory.CreateDirectory(storeFilesDir);
        }

        public Sync(List<Difference> differences, List<TreeNode> arrNodes, SystemType systemName)
        {
            this.differences = differences;
            this.arrNodes = arrNodes;
            this.systemName = systemName;
            folderStack = new Stack<Difference>();


            storeFilesDir = Directory.GetCurrentDirectory();
            storeFilesDir = Path.Combine(storeFilesDir, @"Tzync\Files");
            //Creating the directory
            Directory.CreateDirectory(storeFilesDir);
        }

        //Description     :  
        //Pre-Conditions  : 
        //Post-Conditions : 
        public void Reconcile()
        {
            foreach (Difference d in differences)
            {
                //Console.WriteLine("Malakian: " + d.GetItemType());
                //Console.WriteLine("Malakian: " + d.GetPairType().Second);
                //Console.WriteLine("Malakian: " + systemName);
                //Console.WriteLine("Malakian: " + d.GetPairType().First);
                if (d.GetItemType() == Type.File)
                {
                    ReconcileFile(d);
                }
                else if (d.GetItemType() == Type.Folder)
                {
                    ReconcileFolder(d);
                }
            }
            UpdateFoldersTimeandSize();
        }

        //Description     :  
        //Pre-Conditions  : 
        //Post-Conditions : 
        private void ReconcileFile(Difference d)
        {
            TreeNode tNode;
            DateTimeParser dtp;
            String customFilePath = "";
            FileInfo fileInfo;

            tNode = d.GetPartnerFile();
            dtp = new DateTimeParser(d.GetSysFile().LastWriteTime);
            if (d.GetPairType().Second == OperationType.Creation)
            {
                if (d.GetPairType().First == DirectionType.SystemToHD)
                {
                    if (systemName == SystemType.Host)
                    {
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathA()));
                        if (File.Exists(customFilePath)) File.Delete(customFilePath); // check if earlier file exits. if then juz delete it
                        File.Copy(tNode.getFullPathA(), customFilePath);

                    }
                    else
                    {
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathB()));
                        if (File.Exists(customFilePath)) File.Delete(customFilePath); // check if earlier file exits. if then juz delete it
                        File.Copy(tNode.getFullPathB(), customFilePath);
                    }
                }
                else if (d.GetPairType().First == DirectionType.HDToSystem)
                {
                    if (systemName == SystemType.Host)
                    {
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathB()));
                        File.Copy(Path.Combine(storeFilesDir, customFilePath), tNode.getFullPathA());
                        arrNodes[tNode.getId()].getVersionA().First = tNode.getVersionB().First;
                        arrNodes[tNode.getId()].getVersionA().Second = tNode.getVersionB().Second;
                        fileInfo = new FileInfo(tNode.getFullPathA());
                        dtp = new DateTimeParser(fileInfo.LastWriteTime);
                        arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());
                    }
                    else
                    {
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathA()));
                        File.Copy(Path.Combine(storeFilesDir,customFilePath), tNode.getFullPathB());
                        arrNodes[tNode.getId()].getVersionB().First = tNode.getVersionA().First;
                        arrNodes[tNode.getId()].getVersionB().Second = tNode.getVersionA().Second;
                        fileInfo = new FileInfo(tNode.getFullPathB());
                        dtp = new DateTimeParser(fileInfo.LastWriteTime);
                        arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                    }
                    //Delete file in HD
                    File.Delete(customFilePath);
                }
            }
            else if (d.GetPairType().Second == OperationType.Deletion)
            {
                if (d.GetPairType().First == DirectionType.SystemToHD)
                {
                    if (systemName == SystemType.Host)
                    {
                        arrNodes[tNode.getId()].getVersionA().First = -1;
                        arrNodes[tNode.getId()].getVersionA().Second = 0;
                        dtp = new DateTimeParser(DateTime.Now);
                        arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());

                    }
                    else
                    {

                        arrNodes[tNode.getId()].getVersionB().First = 0;
                        arrNodes[tNode.getId()].getVersionB().Second = -1;
                        dtp = new DateTimeParser(DateTime.Now);
                        arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                    }
                }
                else if (d.GetPairType().First == DirectionType.HDToSystem)
                {
                    if (systemName == SystemType.Host)
                    {
                        File.Delete(tNode.getFullPathA());
                        arrNodes[tNode.getId()].getVersionA().First = tNode.getVersionB().First;
                        arrNodes[tNode.getId()].getVersionA().Second = tNode.getVersionB().Second;
                        dtp = new DateTimeParser(DateTime.Now);
                        arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());
                    }
                    else
                    {
                        File.Delete(tNode.getFullPathB());
                        arrNodes[tNode.getId()].getVersionB().First = tNode.getVersionA().First;
                        arrNodes[tNode.getId()].getVersionB().Second = tNode.getVersionA().Second;
                        dtp = new DateTimeParser(DateTime.Now);
                        arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                    }
                }
            }

            else if (d.GetPairType().Second == OperationType.Modification)
            {
                if (d.GetPairType().First == DirectionType.SystemToHD)
                {
                    if (systemName == SystemType.Host)
                    {
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathA()));
                        if (File.Exists(customFilePath)) File.Delete(customFilePath); // check if earlier file exits. if then juz delete it
                        File.Copy(tNode.getFullPathA(), customFilePath);
                        arrNodes[tNode.getId()].getVersionA().First++;
                        fileInfo = new FileInfo(tNode.getFullPathA());
                        dtp = new DateTimeParser(fileInfo.LastWriteTime);
                        arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());
                    }
                    else
                    {
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathB()));
                        if (File.Exists(customFilePath)) File.Delete(customFilePath); // check if earlier file exits. if then juz delete it
                        File.Copy(tNode.getFullPathB(), customFilePath);
                        arrNodes[tNode.getId()].getVersionB().Second++;
                        fileInfo = new FileInfo(tNode.getFullPathB());
                        dtp = new DateTimeParser(fileInfo.LastWriteTime);
                        arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                    }
                }
                else if (d.GetPairType().First == DirectionType.HDToSystem)
                {
                    if (systemName == SystemType.Host)
                    {
                        if (File.Exists(tNode.getFullPathA())) 
                            File.Delete(tNode.getFullPathA());
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathB()));
                        File.Copy(Path.Combine(storeFilesDir, customFilePath), tNode.getFullPathA()); 
                        arrNodes[tNode.getId()].getVersionA().First = tNode.getVersionB().First;
                        arrNodes[tNode.getId()].getVersionA().Second = tNode.getVersionB().Second;
                        fileInfo = new FileInfo(tNode.getFullPathA());
                        dtp = new DateTimeParser(fileInfo.LastWriteTime);
                        arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());
                    }
                    else
                    {
                        if (File.Exists(tNode.getFullPathB()))
                            File.Delete(tNode.getFullPathB());
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathA()));
                        File.Copy(Path.Combine(storeFilesDir, customFilePath), tNode.getFullPathB());
                        arrNodes[tNode.getId()].getVersionB().First = tNode.getVersionA().First;
                        arrNodes[tNode.getId()].getVersionB().Second = tNode.getVersionA().Second;
                        fileInfo = new FileInfo(tNode.getFullPathB());
                        dtp = new DateTimeParser(fileInfo.LastWriteTime);
                        arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                    }
                    //Delete file in HD
                    File.Delete(customFilePath);
                }
            }

            else if (d.GetPairType().Second == OperationType.ModModConflict)
            {
                if (d.GetPairType().First == DirectionType.SystemToHD)
                {
                    if (systemName == SystemType.Host)
                    {
                        // delete B's file in HD since user want to propagate system file to HD
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathB()));
                        File.Delete(customFilePath);
                        // copy system file to HD now
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathA()));
                        File.Copy(tNode.getFullPathA(), customFilePath);
                        arrNodes[tNode.getId()].getVersionA().First++;
                        fileInfo = new FileInfo(tNode.getFullPathA());
                        dtp = new DateTimeParser(fileInfo.LastWriteTime);
                        arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());
                    }
                    else
                    {
                        // delete A's file in HD since user want to propagate system file to HD
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathA()));
                        File.Delete(customFilePath);
                        // copy system file to HD now
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathB()));
                        File.Copy(tNode.getFullPathB(), customFilePath);
                        arrNodes[tNode.getId()].getVersionB().Second++;
                        fileInfo = new FileInfo(tNode.getFullPathB());
                        dtp = new DateTimeParser(fileInfo.LastWriteTime);
                        arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                    }
                }
                else if (d.GetPairType().First == DirectionType.HDToSystem)
                {
                    if (systemName == SystemType.Host)
                    {
                        File.Delete(tNode.getFullPathA());
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathB()));
                        File.Copy(Path.Combine(storeFilesDir, customFilePath), tNode.getFullPathA()); 
                        arrNodes[tNode.getId()].getVersionA().First = tNode.getVersionB().First;
                        arrNodes[tNode.getId()].getVersionA().Second = tNode.getVersionB().Second;
                        fileInfo = new FileInfo(tNode.getFullPathA());
                        dtp = new DateTimeParser(fileInfo.LastWriteTime);
                        arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());
                    }
                    else
                    {
                        File.Delete(tNode.getFullPathB());
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathA()));
                        File.Copy(Path.Combine(storeFilesDir, customFilePath), tNode.getFullPathB());
                        arrNodes[tNode.getId()].getVersionB().First = tNode.getVersionA().First;
                        arrNodes[tNode.getId()].getVersionB().Second = tNode.getVersionA().Second;
                        fileInfo = new FileInfo(tNode.getFullPathB());
                        dtp = new DateTimeParser(fileInfo.LastWriteTime);
                        arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                    }
                    //Delete file in HD
                    File.Delete(customFilePath);
                }
            }

            else if (d.GetPairType().Second == OperationType.ModDeleteConflict)
            {
                if (d.GetPairType().First == DirectionType.SystemToHD)
                {
                    if (systemName == SystemType.Host)
                    {
                        if (arrNodes[tNode.getId()].getVersionB().First == 0 && arrNodes[tNode.getId()].getVersionB().Second == -1)
                        {
                            customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathA()));
                            if (File.Exists(customFilePath)) File.Delete(customFilePath); // check if earlier file exits. if then juz delete it
                            File.Copy(tNode.getFullPathA(), customFilePath);
                            arrNodes[tNode.getId()].getVersionA().First++;
                            fileInfo = new FileInfo(tNode.getFullPathA());
                            dtp = new DateTimeParser(fileInfo.LastWriteTime);
                            arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());
                        }
                        else
                        {
                            arrNodes[tNode.getId()].getVersionA().First = -1;
                            arrNodes[tNode.getId()].getVersionA().Second = 0;
                            dtp = new DateTimeParser(DateTime.Now);
                            arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());
                        }

                    }
                    else
                    {
                        if (arrNodes[tNode.getId()].getVersionA().First == -1 && arrNodes[tNode.getId()].getVersionA().Second == 0)
                        {
                            customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathB()));
                            if (File.Exists(customFilePath)) File.Delete(customFilePath); // check if earlier file exits. if then juz delete it
                            File.Copy(tNode.getFullPathB(), customFilePath);
                            arrNodes[tNode.getId()].getVersionB().Second++;
                            fileInfo = new FileInfo(tNode.getFullPathB());
                            dtp = new DateTimeParser(fileInfo.LastWriteTime);
                            arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                        }
                        else
                        {
                            arrNodes[tNode.getId()].getVersionB().First = 0;
                            arrNodes[tNode.getId()].getVersionB().Second = -1;
                            dtp = new DateTimeParser(DateTime.Now);
                            arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                        }
                    }
                }
                else if (d.GetPairType().First == DirectionType.HDToSystem)
                {
                    if (systemName == SystemType.Host)
                    {
                        if (arrNodes[tNode.getId()].getVersionB().First == 0 && arrNodes[tNode.getId()].getVersionB().Second == -1)
                        {
                            File.Delete(tNode.getFullPathA());
                            arrNodes[tNode.getId()].getVersionA().First = tNode.getVersionB().First;
                            arrNodes[tNode.getId()].getVersionA().Second = tNode.getVersionB().Second;
                            dtp = new DateTimeParser(DateTime.Now);
                            arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());
                        }
                        else
                        {
                            customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathB()));
                            File.Copy(Path.Combine(storeFilesDir, customFilePath), tNode.getFullPathA()); 
                            arrNodes[tNode.getId()].getVersionA().First = tNode.getVersionB().First;
                            arrNodes[tNode.getId()].getVersionA().Second = tNode.getVersionB().Second;
                            fileInfo = new FileInfo(tNode.getFullPathA());
                            dtp = new DateTimeParser(fileInfo.LastWriteTime);
                            arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());
                            //Delete file in HD
                            File.Delete(customFilePath);
                        }

                    }
                    else
                    {
                        if (arrNodes[tNode.getId()].getVersionA().First == -1 && arrNodes[tNode.getId()].getVersionA().Second == 0)
                        {
                            File.Delete(tNode.getFullPathB());
                            arrNodes[tNode.getId()].getVersionB().First = tNode.getVersionA().First;
                            arrNodes[tNode.getId()].getVersionB().Second = tNode.getVersionA().Second;
                            dtp = new DateTimeParser(DateTime.Now);
                            arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                        }
                        else
                        {
                            customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathA()));
                            File.Copy(Path.Combine(storeFilesDir, customFilePath), tNode.getFullPathB());
                            arrNodes[tNode.getId()].getVersionB().First = tNode.getVersionA().First;
                            arrNodes[tNode.getId()].getVersionB().Second = tNode.getVersionA().Second;
                            fileInfo = new FileInfo(tNode.getFullPathB());
                            dtp = new DateTimeParser(fileInfo.LastWriteTime);
                            arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                            //Delete file in HD
                            File.Delete(customFilePath);
                        }
                    }
                }
            }
            else if (d.GetPairType().Second == OperationType.CreationCreationConflict)
            {
                if (d.GetPairType().First == DirectionType.SystemToHD)
                {
                    if (systemName == SystemType.Host)
                    {
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathA()));
                        if (File.Exists(customFilePath)) File.Delete(customFilePath); // check if earlier file exits. if then juz delete it
                        File.Copy(tNode.getFullPathA(), customFilePath);
                        arrNodes[tNode.getId()].getVersionA().First++;
                        fileInfo = new FileInfo(tNode.getFullPathA());
                        dtp = new DateTimeParser(fileInfo.LastWriteTime);
                        arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());
                    }
                    else
                    {
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathB()));
                        if (File.Exists(customFilePath)) File.Delete(customFilePath); // check if earlier file exits. if then juz delete it
                        File.Copy(tNode.getFullPathB(), customFilePath);
                        arrNodes[tNode.getId()].getVersionB().Second++;
                        fileInfo = new FileInfo(tNode.getFullPathB());
                        dtp = new DateTimeParser(fileInfo.LastWriteTime);
                        arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                    }
                }
                else if (d.GetPairType().First == DirectionType.HDToSystem)
                {
                    if (systemName == SystemType.Host)
                    {
                        File.Delete(tNode.getFullPathA());
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathB()));
                        File.Copy(Path.Combine(storeFilesDir, customFilePath), tNode.getFullPathA()); 
                        arrNodes[tNode.getId()].getVersionA().First = tNode.getVersionB().First;
                        arrNodes[tNode.getId()].getVersionA().Second = tNode.getVersionB().Second;
                        fileInfo = new FileInfo(tNode.getFullPathA());
                        dtp = new DateTimeParser(fileInfo.LastWriteTime);
                        arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());
                    }
                    else
                    {
                        File.Delete(tNode.getFullPathB());
                        customFilePath = Path.Combine(storeFilesDir, StripString(tNode.getFullPathA()));
                        File.Copy(Path.Combine(storeFilesDir, customFilePath), tNode.getFullPathB());
                        arrNodes[tNode.getId()].getVersionB().First = tNode.getVersionA().First;
                        arrNodes[tNode.getId()].getVersionB().Second = tNode.getVersionA().Second;
                        fileInfo = new FileInfo(tNode.getFullPathB());
                        dtp = new DateTimeParser(fileInfo.LastWriteTime);
                        arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                    }
                    //Delete file in HD
                    File.Delete(customFilePath);
                }
            }
            else if (d.GetPairType().Second == OperationType.DeletionDeletionConflict)
            {
                if (d.GetPairType().First == DirectionType.SystemToHD)
                {
                    if (systemName == SystemType.Host)
                    {
                        arrNodes[tNode.getId()].getVersionA().First = -1;
                        arrNodes[tNode.getId()].getVersionA().Second = 0;
                        dtp = new DateTimeParser(DateTime.Now);
                        arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());
                    }
                    else
                    {
                        arrNodes[tNode.getId()].getVersionB().First = 0;
                        arrNodes[tNode.getId()].getVersionB().Second = -1;
                        dtp = new DateTimeParser(DateTime.Now);
                        arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                    }
                }
                else if (d.GetPairType().First == DirectionType.HDToSystem)
                {
                    if (systemName == SystemType.Host)
                    {
                        arrNodes[tNode.getId()].getVersionA().First = 0;
                        arrNodes[tNode.getId()].getVersionA().Second = -1;
                        dtp = new DateTimeParser(DateTime.Now);
                        arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());
                    }
                    else
                    {
                        arrNodes[tNode.getId()].getVersionB().First = -1;
                        arrNodes[tNode.getId()].getVersionB().Second = 0;
                        dtp = new DateTimeParser(DateTime.Now);
                        arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                    }
                }
            }
        }

        //Description     :  
        //Pre-Conditions  : 
        //Post-Conditions : 
        private void ReconcileFolder(Difference d)
        {
            TreeNode tNode;
            tNode = d.GetPartnerFolder();
            folderStack.Push(d);
            if (d.GetPairType().Second == OperationType.Creation)
            {
                if (d.GetPairType().First == DirectionType.SystemToHD)
                {
                }
                else
                {
                    if (systemName == SystemType.Host)
                    {
                        if (tNode.getFullPathA().Length == 0)
                        {
                            TreeNode tParentNode;
                            tParentNode = arrNodes[tNode.getParent()];
                            Directory.CreateDirectory(Path.Combine(tParentNode.getFullPathA(),tNode.getName()));
                            arrNodes[tNode.getId()].setFullPathA(Path.Combine(tParentNode.getFullPathA(), tNode.getName()));
                            tNode.setFullPathA(Path.Combine(tParentNode.getFullPathA(), tNode.getName()));
                        }
                        else
                        { 
                            Directory.CreateDirectory(tNode.getFullPathA()); 
                        }
                        arrNodes[tNode.getId()].getVersionA().First = tNode.getVersionB().First;
                        arrNodes[tNode.getId()].getVersionA().Second = tNode.getVersionB().Second;
                    }
                    else
                    {
                        Directory.CreateDirectory(tNode.getFullPathB());
                        arrNodes[tNode.getId()].getVersionB().First = tNode.getVersionA().First;
                        arrNodes[tNode.getId()].getVersionB().Second = tNode.getVersionA().Second;
                    }
                }

            }
            else if (d.GetPairType().Second == OperationType.Modification)
            {
                if (d.GetPairType().First == DirectionType.SystemToHD)
                {
                    if (systemName == SystemType.Host)
                    {
                        arrNodes[tNode.getId()].getVersionA().First++;
                    }
                    else
                    {
                        arrNodes[tNode.getId()].getVersionB().Second++;
                    }
                }
                else
                {
                    if (systemName == SystemType.Host)
                    {
                        arrNodes[tNode.getId()].getVersionA().First = tNode.getVersionB().First;
                        arrNodes[tNode.getId()].getVersionA().Second = tNode.getVersionB().Second;
                    }
                    else
                    {
                        arrNodes[tNode.getId()].getVersionB().First = tNode.getVersionA().First;
                        arrNodes[tNode.getId()].getVersionB().Second = tNode.getVersionA().Second;
                    }
                }
            }
            else if (d.GetPairType().Second == OperationType.Deletion)
            {
                if (d.GetPairType().First == DirectionType.SystemToHD)
                {
                    if (systemName == SystemType.Host)
                    {
                        arrNodes[tNode.getId()].getVersionA().First = -1;
                        arrNodes[tNode.getId()].getVersionA().Second = 0;
                    }
                    else
                    {
                        arrNodes[tNode.getId()].getVersionB().First = 0;
                        arrNodes[tNode.getId()].getVersionB().Second = -1;
                    }
                }
                else
                {
                    if (systemName == SystemType.Host)
                    {
                        arrNodes[tNode.getId()].getVersionA().First = tNode.getVersionB().First;
                        arrNodes[tNode.getId()].getVersionA().Second = tNode.getVersionB().Second;
                    }
                    else
                    {
                        arrNodes[tNode.getId()].getVersionB().First = tNode.getVersionA().First;
                        arrNodes[tNode.getId()].getVersionB().Second = tNode.getVersionA().Second;
                    }
                }
            }
            else if (d.GetPairType().Second == OperationType.ModModConflict) // same as Modification...how?
            {
                if (d.GetPairType().First == DirectionType.SystemToHD)
                {
                    if (systemName == SystemType.Host)
                    {
                        arrNodes[tNode.getId()].getVersionA().First++;
                    }
                    else
                    {
                        arrNodes[tNode.getId()].getVersionB().Second++;
                    }
                }
                else
                {
                    if (systemName == SystemType.Host)
                    {
                        arrNodes[tNode.getId()].getVersionA().First = tNode.getVersionB().First;
                        arrNodes[tNode.getId()].getVersionA().Second = tNode.getVersionB().Second;
                    }
                    else
                    {
                        arrNodes[tNode.getId()].getVersionB().First = tNode.getVersionA().First;
                        arrNodes[tNode.getId()].getVersionB().Second = tNode.getVersionA().Second;
                    }
                }
            }
            else if (d.GetPairType().Second == OperationType.ModDeleteConflict)
            {
                if (d.GetPairType().First == DirectionType.SystemToHD)
                {
                    if (systemName == SystemType.Host)
                    {
                        if (arrNodes[tNode.getId()].getVersionB().First == 0 && arrNodes[tNode.getId()].getVersionB().Second == -1)
                        {
                            arrNodes[tNode.getId()].getVersionA().First++;
                        }
                        else
                        {
                            arrNodes[tNode.getId()].getVersionA().First = -1;
                            arrNodes[tNode.getId()].getVersionA().Second = 0;
                        }

                    }
                    else
                    {
                        if (arrNodes[tNode.getId()].getVersionA().First == -1 && arrNodes[tNode.getId()].getVersionA().Second == 0)
                        {
                            arrNodes[tNode.getId()].getVersionB().Second++;
                        }
                        else
                        {
                            arrNodes[tNode.getId()].getVersionB().First = 0;
                            arrNodes[tNode.getId()].getVersionB().Second = -1;
                        }
                    }
                }
                else
                {
                    if (systemName == SystemType.Host)
                    {
                        if (arrNodes[tNode.getId()].getVersionB().First == 0 && arrNodes[tNode.getId()].getVersionB().Second == -1)
                        {
                            //Change to delete operation so that folder can be deleted in reconcileFolders method
                            d.SetPairType(new Pair<DirectionType, OperationType>(d.GetPairType().First, OperationType.Deletion));
                            arrNodes[tNode.getId()].getVersionA().First = tNode.getVersionB().First;
                            arrNodes[tNode.getId()].getVersionA().Second = tNode.getVersionB().Second;
                        }
                        else
                        {
                            arrNodes[tNode.getId()].getVersionA().First = tNode.getVersionB().First;
                            arrNodes[tNode.getId()].getVersionA().Second = tNode.getVersionB().Second;
                        }

                    }
                    else
                    {
                        if (arrNodes[tNode.getId()].getVersionA().First == -1 && arrNodes[tNode.getId()].getVersionA().Second == 0)
                        {
                            //Change to delete operation so that folder can be deleted in reconcileFolders method
                            d.SetPairType(new Pair<DirectionType, OperationType>(d.GetPairType().First, OperationType.Deletion));
                            arrNodes[tNode.getId()].getVersionB().First = tNode.getVersionA().First;
                            arrNodes[tNode.getId()].getVersionB().Second = tNode.getVersionA().Second;
                        }
                        else
                        {
                            arrNodes[tNode.getId()].getVersionB().First = tNode.getVersionA().First;
                            arrNodes[tNode.getId()].getVersionB().Second = tNode.getVersionA().Second;
                        }
                    }
                }
            }
            else if (d.GetPairType().Second == OperationType.CreationCreationConflict)
            {
                if (d.GetPairType().First == DirectionType.SystemToHD)
                {
                    if (systemName == SystemType.Host)
                    {
                        arrNodes[tNode.getId()].getVersionA().First++;
                    }
                    else
                    {
                        arrNodes[tNode.getId()].getVersionB().Second++;
                    }
                }
                else
                {
                    if (systemName == SystemType.Host)
                    {
                        arrNodes[tNode.getId()].getVersionA().First = tNode.getVersionB().First;
                        arrNodes[tNode.getId()].getVersionA().Second = tNode.getVersionB().Second;
                    }
                    else
                    {
                        arrNodes[tNode.getId()].getVersionB().First = tNode.getVersionA().First;
                        arrNodes[tNode.getId()].getVersionB().Second = tNode.getVersionA().Second;
                    }
                }
            }
            else if (d.GetPairType().Second == OperationType.DeletionDeletionConflict)
            {
                if (d.GetPairType().First == DirectionType.SystemToHD)
                {
                    if (systemName == SystemType.Host)
                    {
                        arrNodes[tNode.getId()].getVersionA().First = -1;
                        arrNodes[tNode.getId()].getVersionA().Second = 0;
                    }
                    else
                    {
                        arrNodes[tNode.getId()].getVersionB().First = 0;
                        arrNodes[tNode.getId()].getVersionB().Second = -1;
                    }
                }
                else
                {
                    if (systemName == SystemType.Host)
                    {
                        arrNodes[tNode.getId()].getVersionA().First = 0;
                        arrNodes[tNode.getId()].getVersionA().Second = -1;
                    }
                    else
                    {
                        arrNodes[tNode.getId()].getVersionB().First = -1;
                        arrNodes[tNode.getId()].getVersionB().Second = 0;
                    }
                }
            }
            //UpdateFoldersTimeandSize();
        }

        private void UpdateFoldersTimeandSize()
        {
            TreeNode tNode;
            DateTimeParser dtp;
            DirectoryInfo dirInfo;

            foreach (Difference d in folderStack)
            {
                //Console.WriteLine(d.GetItemType());
                //Console.WriteLine(d.GetPairType().Second);
                //Console.WriteLine(systemName);
                //Console.WriteLine(d.GetPairType().First);

                tNode = d.GetPartnerFolder();
                if (d.GetPairType().Second == OperationType.Deletion)
                {
                    dtp = new DateTimeParser(DateTime.Now);
                    if (d.GetPairType().First == DirectionType.SystemToHD)
                    {
                        if (systemName == SystemType.Host)
                        {
                            arrNodes[tNode.getId()].setSizeA(0);
                            arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());
                        }
                        else
                        {
                            arrNodes[tNode.getId()].setSizeB(0);
                            arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                        }
                    }
                    else
                    {
                        if (systemName == SystemType.Host)
                        {
                            // The directory's child are already deleted before executing this statement
                            Directory.Delete(tNode.getFullPathA());
                            arrNodes[tNode.getId()].setSizeA(0);
                            arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());
                        }
                        else
                        {
                            // The directory's child are already deleted before before executing this statement
                            Directory.Delete(tNode.getFullPathB());
                            arrNodes[tNode.getId()].setSizeB(0);
                            arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                        }
                    }
                }
                else // other folders that are not delete type can be updated as normal
                {
                    //dirInfo = new DirectoryInfo(tNode.getFullPathA());
                    //long directorySize = CalculateDirectorySize(d.GetSysFolder());
                    //dtp = new DateTimeParser(d.GetSysFolder().LastWriteTime);
                    //Console.WriteLine(dtp.GetNewDateTime());
                    if (systemName == SystemType.Host)
                    {
                        dirInfo = new DirectoryInfo(tNode.getFullPathA());
                        long directorySize = CalculateDirectorySize(dirInfo);
                        dtp = new DateTimeParser(dirInfo.LastWriteTime);
                        //Console.WriteLine(dtp.GetNewDateTime());
                        arrNodes[tNode.getId()].setSizeA(directorySize);
                        arrNodes[tNode.getId()].setSyncA(dtp.GetNewDateTime());
                    }
                    else
                    {
                        dirInfo = new DirectoryInfo(tNode.getFullPathB());
                        long directorySize = CalculateDirectorySize(dirInfo);
                        dtp = new DateTimeParser(dirInfo.LastWriteTime);
                        //Console.WriteLine(dtp.GetNewDateTime());
                        arrNodes[tNode.getId()].setSizeB(directorySize);
                        arrNodes[tNode.getId()].setSyncB(dtp.GetNewDateTime());
                    }
                }
            }
        }

        public void CopyFilesToHD(DirectoryInfo source)
        {            
            DirectoryInfo destination = new DirectoryInfo(storeFilesDir);
            destination = new DirectoryInfo(Path.Combine(destination.FullName, source.Name));
            CopyDirectory(source, destination);
        }

        public String CopyFilesToSystem(DirectoryInfo destination)
        {
            rootAddress = destination.FullName;
            rootAddress = Path.Combine(rootAddress, arrNodes[0].getName());

            if (Directory.Exists(rootAddress)) DeleteDirectory(new DirectoryInfo(rootAddress)); //Directory.Delete(rootAddress, true);

            DirectoryInfo source = new DirectoryInfo(storeFilesDir);
            CopyDirectory(source, destination);
            updateArrNodesForSecondTime();
            //Directory.Delete(source.FullName, true);
            DeleteDirectory(source);
            Directory.Delete(source.FullName, true);


            return rootAddress;
        }

        private void updateArrNodesForSecondTime()
        {
            DateTimeParser dtp;
            TreeNode tParentNode = arrNodes[0];
            int count = 0;
            DirectoryInfo d,rootB= new DirectoryInfo(rootAddress);

            TreeOperation t = new TreeOperation(arrNodes, secondTime,systemName);
            t.UpdateRootNodeB(rootB, arrNodes[0]);

            foreach (TreeNode tNode in arrNodes)
            {
                tParentNode = arrNodes[tNode.getParent()];
                if (count != 0)
                {
                    tNode.setFullPathB(Path.Combine(tParentNode.getFullPathB(), tNode.getName()));
                }
                if (tNode.getType() == Type.File)
                {
                    dtp = new DateTimeParser(tNode.getSyncA());
                    tNode.setSyncB(dtp.GetNewDateTime());
                }
                else
                {
                    d = new DirectoryInfo(tNode.getFullPathB());
                    dtp = new DateTimeParser(d.LastWriteTime);
                    tNode.setSyncB(dtp.GetNewDateTime());
                }
                tNode.setSizeB(tNode.getSizeA());
                tNode.setVersionB(tNode.getVersionA());
                
                count++;
            }
        }
        
        private void CopyDirectory(DirectoryInfo source, DirectoryInfo destination)
        {

            if (!destination.Exists)
            {
                try
                {
                    destination.Create();
                }
                catch (UnauthorizedAccessException)
                {
                }
            }

            // Copy all files.
            FileInfo[] files = source.GetFiles();
            String filePath = "";
            FileAttributes fileAtts;
            foreach (FileInfo file in files)
            {
                filePath = Path.Combine(destination.FullName, file.Name);
                if (!File.Exists(filePath))
                {
                    fileAtts = File.GetAttributes(file.FullName);
                    File.SetAttributes(file.FullName, fileAtts & ~FileAttributes.ReadOnly);
                    try
                    {
                        file.CopyTo(Path.Combine(@"\\?\UNC", filePath));
                    }
                    catch (UnauthorizedAccessException)
                    {
                    }
                    catch (PathTooLongException)
                    {
                    }
                }
            }

            // Process subdirectories.
            DirectoryInfo[] dirs = source.GetDirectories();
            foreach (DirectoryInfo dir in dirs)
            {
                string destinationDir = Path.Combine(destination.FullName, dir.Name);

                // Call CopyDirectory() recursively.
                CopyDirectory(dir, new DirectoryInfo(destinationDir));
            }
        }

        public void DeleteDirectory(DirectoryInfo dirInfo)
        {
            // Copy all files.
            FileInfo[] files = dirInfo.GetFiles();
            FileAttributes fileAtts;
            DirectoryInfo dirDest;
            foreach (FileInfo file in files)
            {
                fileAtts = File.GetAttributes(file.FullName);
                File.SetAttributes(file.FullName, fileAtts & ~FileAttributes.ReadOnly);
                file.Delete();
            }

            // Process subdirectories.
            DirectoryInfo[] dirs = dirInfo.GetDirectories();
            foreach (DirectoryInfo dir in dirs)
            {
                string destinationDir = Path.Combine(dirInfo.FullName, dir.Name);
                dirDest = new DirectoryInfo(destinationDir);

                // Call CopyDirectory() recursively.
                DeleteDirectory(dirDest);
                dirDest.Delete();
            }
        }

        private long CalculateDirectorySize(DirectoryInfo directory)
        {
            long totalSize = 0;

            // Examine all contained files.
            FileInfo[] files = directory.GetFiles();
            foreach (FileInfo file in files)
            {
                totalSize += file.Length;
            }

            DirectoryInfo[] dirs = directory.GetDirectories();
            foreach (DirectoryInfo dir in dirs)
            {
                totalSize += CalculateDirectorySize(dir);
            }

            return totalSize;
        }

        private String StripString(String input)
        {
            String[] arrWords;
            String concat = "";
            arrWords = input.Split('\\',':');
            foreach (String str in arrWords)
            {
                concat += str;
            }
            return concat;
        }


    }
}
